﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EffectInfo
{
    public uint delayId;
    public GameObject go;
}

public class ParticleInfo
{
    public int effectId;
    public string effectPath;
    public ParticleSystem ps;
}

public class ScreenEffectsMgr
{
    private Transform trans = null;
    private List<string> loadingList;
    private static Dictionary<string, EffectInfo> effectDic;
    private static List<ParticleInfo> particleInfos;

    public ScreenEffectsMgr()
    {
        Init();
    }
   
    private void Init()
    {
        loadingList = new List<string>();
        particleInfos = new List<ParticleInfo>();
        effectDic = new Dictionary<string, EffectInfo>();
        trans = AllUpdate.GetChildByName("ScreenEff");
        Utility.SetActive(trans, true);
        ZEventCenter.AddEventListener(ConstData.SCENE_LOAD_START, OnStartLoadScene);
    }

    private void OnStartLoadScene(ZEvent ev)
    {
        Clear();
    }

    public void Clear()
    {
        foreach (var item in effectDic)
        {
            Object.Destroy(item.Value.go);
            ZMgr.TimerMgr.ClearTimeOut(item.Value.delayId);
        }
        effectDic.Clear();
    }

    /// <summary>
    /// 添加播放特效  不需返回粒子特效的
    /// </summary>
    /// <param name="path">特效资源路径</param>
    /// <param name="time">播放时长 单位秒</param>
    /// <param name="isTop">是否显示在最上层</param>
    public void AddEffect(string path, float time, bool isTop, string key = null)
    {
        BehaviourUtil.StartCoroutine(RunEffect(path, time, isTop, key, null));
    }

    /// <summary>
    /// 添加播放特效
    /// </summary>
    /// <param name="path">特效资源路径</param>
    /// <param name="time">播放时长 单位秒</param>
    /// <param name="isTop">是否显示在最上层</param>
    private IEnumerator RunEffect(string path, float time, bool isTop, string key, OnLoadArg arg)
    {
        if (string.IsNullOrEmpty(key))
        {
            key = path;
        }
        Label_waitLoad:
        if (loadingList.Contains(key))
        {
            yield return 0;
            goto Label_waitLoad;
        }

        if (effectDic != null && effectDic.ContainsKey(key))
        {
            if (time > 0)
            {
                //做重播处理
                Utility.SetActive(effectDic[key].go, true);
                ParticleSystem[] particle = effectDic[key].go.GetComponentsInChildren<ParticleSystem>();
                for (int i = 0; i < particle.Length; i++)
                {
                    particle[i].Stop();
                    particle[i].Clear();
                    particle[i].Play();
                }
                ZMgr.TimerMgr.ClearTimeOut(effectDic[key].delayId);
                effectDic[key].delayId = ZMgr.TimerMgr.SetTimeOut(PlayedCallBack, time, key);
            }
            if (arg != null)
            {
                arg.asset = effectDic[key].go;
                arg.loadOk = true;
            }
            yield break;
        }

        loadingList.Add(key);
        OnLoadArg loadArg = new OnLoadArg();
        yield return BehaviourUtil.StartCoroutine(ZMgr.ResourceMgr.CoroutineLoad(path + ".prefab.uab", loadArg));

        GameObject go = loadArg.asset as GameObject;
        ResourceMgr.FixShader(go);
        go = NGUITools.AddChild(trans.gameObject, go);
        EffectInfo effectInfo = new EffectInfo();

        effectInfo.go = go;
        if (time > 0)
        {
            effectInfo.delayId = ZMgr.TimerMgr.SetTimeOut(PlayedCallBack, time, key);
        }

        effectDic.Add(key, effectInfo);
        loadingList.Remove(key);
        Renderer[] renderers = go.GetComponentsInChildren<Renderer>();
        for (int i = 0; i < renderers.Length; i++)
        {
            renderers[i].sharedMaterial.renderQueue = isTop ? 9999 : 1;
        }

        if (arg != null)
        {
            arg.asset = go;
            arg.loadOk = true;
        }
    }

    private void PlayedCallBack(string key)
    {
        Utility.SetActive(effectDic[key].go, false);
    }

    public void PlayEffect(int effectId, List<GameObject> objs)
    {
        BehaviourUtil.StartCoroutine(RunPlayEffect(effectId, objs));
    }

    public IEnumerator RunPlayEffect(int effectId, List<GameObject> objs)
    {
        var table_Effect = TableDataMgr.EffectMgr.GetItemById(effectId);
        if (table_Effect == null) { yield break; }

        int effectCount = 1;
        if (objs != null)
        {
            effectCount = objs.Count;
        }
        if (particleInfos == null)
        {
            particleInfos = new List<ParticleInfo>();
        }

        if ((particleInfos.Count < effectCount))
        {
            for (int i = particleInfos.Count; i < objs.Count; i++)
            {
                OnLoadArg arg = new OnLoadArg();
                string strPath = table_Effect.Path + i.ToString();
                yield return BehaviourUtil.StartCoroutine(RunEffect(strPath, 0, true, table_Effect.Path, arg));

                GameObject go = arg.asset as GameObject;
                Vector3 pos = objs[i].transform.position;
                go.transform.localPosition = GameTool.PositionToUI(pos);

                ParticleInfo info = new ParticleInfo();
                info.ps = go.GetComponent<ParticleSystem>();

                info.effectPath = table_Effect.Path;
                info.effectId = effectId;
                particleInfos.Add(info);
            }
        }

        for (int i = 0; i < particleInfos.Count; i++)
        {
            if ((i < effectCount) && (particleInfos[i].effectId == effectId))
            {
                Utility.SetActive(particleInfos[i].ps, true);
                particleInfos[i].ps.Stop();
                particleInfos[i].ps.Clear();
                particleInfos[i].ps.Play();
            }
        }
        //ZMgr.TimerMgr.SetTimeOut(DelayFun, 4);
    }

    public void DelayFun()
    {
        if (particleInfos == null) { return; }
        for (int i = 0; i < particleInfos.Count; i++)
        {
            Utility.SetActive(particleInfos[i].ps, false);
        }
    }
    
    public void RemoveEffect(string key)
    {
        if (effectDic.ContainsKey(key))
        {
            Object.Destroy(effectDic[key].go);
            effectDic.Remove(key);
        }
    }

    public void RemoveAllEffect()
    {
        if (particleInfos == null) { return; }
        for (int i = 0; i < particleInfos.Count; i++)
        {
            particleInfos[i].ps.Stop();
            particleInfos[i].ps.Clear();
            RemoveEffect(particleInfos[i].effectPath);
        }
        particleInfos.Clear();
    }

    public static void StopAllEffect()
    {
        if (particleInfos == null) { return; }
        for (int i = 0; i < particleInfos.Count; i++)
        {
            particleInfos[i].ps.Stop();
            particleInfos[i].ps.Clear();
        }
    }
}